﻿using System.Collections.Generic;
using Caliburn.Micro;
using Cookbook.Common;
using Cooking.Client.CaliburnExtensions;
using Cooking.Client.Commanding;
using Cooking.Client.Services;
using Cooking.Client.ViewModels.Coroutines;

namespace Cooking.Client.ViewModels
{
    public class NewRecipeViewModel : EditableScreen
    {
        #region Private Definitions

        private string recipeTitle;
        private string description;
        private IModalView modalView;

        private readonly ICommandAgent commandAgent;

        #endregion

        public NewRecipeViewModel(ICommandAgent commandAgent)
        {
            this.commandAgent = commandAgent;
        }

        public string RecipeTitle
        {
            get { return recipeTitle; }
            set
            {
                if (recipeTitle != value)
                {
                    Validate(() => RecipeTitle, ClientRule.RecipeTitleIsRequired, () => !string.IsNullOrEmpty(value));

                    Coroutine.BeginExecute(VerifyTitleUniqueness(value).GetEnumerator());

                    recipeTitle = value;

                    NotifyOfPropertyChange(() => RecipeTitle);
                    NotifyOfPropertyChange(() => CanSave);
                }
            }
        }

        private IEnumerable<IResult> VerifyTitleUniqueness(string value)
        {
            if (value.IsNotNullOrEmpty())
            {
                var coroutine = Routines.EnsureRecipeTitleUniqueness(value);
                yield return coroutine;

                Validate(() => RecipeTitle, ClientRule.RecipeTitleMustBeUnique, () => coroutine.IsUnique);
            }
        }

        public string Description
        {
            get { return description; }
            set
            {
                if (description != value)
                {
                    Validate(() => Description, ClientRule.RecipeDescriptionIsRequired,
                             () => !string.IsNullOrEmpty(value));

                    description = value;

                    NotifyOfPropertyChange(() => Description);
                    NotifyOfPropertyChange(() => CanSave);
                }
            }
        }

        public void Activate()
        {
            RecipeTitle = "";
            Description = "";
        }

        public void Save()
        {
            if (CanSave)
            {
                commandAgent.Send(new AddNewRecipeCommand
                {
                    Title = RecipeTitle,
                    Description = Description
                });

                modalView.Close();
            }
        }

        public bool CanSave
        {
            get { return !HasErrors; }
        }

        public void Cancel()
        {
            modalView.Close();
        }

        /// <summary>
        /// Called when a view is attached.
        /// </summary>
        /// <param name="view">The view.</param>
        /// <param name="context">The context in which the view appears.</param>
        protected override void OnViewAttached(object view, object context)
        {
            modalView = (IModalView)view;
        }
    }

    public interface IModalView
    {
        void Close();
    }
}